package gek.uni.diplom.ocl.example.commands;

import gek.uni.diplom.ocl.example.utils.junit.JUnitFileDesc;
import gek.uni.diplom.ocl.example.utils.junit.MethodDescription;

import java.io.File;
import java.util.Iterator;

import org.eclipse.core.commands.ExecutionEvent;
import org.eclipse.core.commands.ExecutionException;
import org.eclipse.core.commands.IHandler;
import org.eclipse.core.commands.IHandlerListener;
import org.eclipse.emf.common.util.EList;
import org.eclipse.emf.common.util.URI;
import org.eclipse.emf.ecore.EObject;
import org.eclipse.emf.ecore.resource.Resource;
import org.eclipse.emf.ecore.resource.ResourceSet;
import org.eclipse.emf.ecore.resource.impl.ResourceSetImpl;
import org.eclipse.emf.ecore.xmi.impl.EcoreResourceFactoryImpl;

import RootDesc.RootDescPackage;
import RootDesc.RootDescription;
import RootDesc.TestDescription;

public class Command2Handler implements IHandler {

  @Override
  public void addHandlerListener(IHandlerListener handlerListener) {

  }

  @Override
  public void dispose() {

  }

  @Override
  public Object execute(ExecutionEvent event) throws ExecutionException {
    loadEMFResource();
    return null;
  }

  private void loadEMFResource() {
    ResourceSet resourceSet = new ResourceSetImpl();
    resourceSet.getResourceFactoryRegistry().getExtensionToFactoryMap().put(
        Resource.Factory.Registry.DEFAULT_EXTENSION,
        new EcoreResourceFactoryImpl());
    resourceSet.getPackageRegistry().put(RootDescPackage.eNAME,
        RootDescPackage.eINSTANCE);
    String fileName = "D:\\example_tfg.xml";
    URI uri = URI.createPlatformResourceURI("gek.uni.diplom.tfg.atl.transform/out.xml",true);
    File file = new File(uri.toFileString());
    Resource resource = resourceSet.getResource(uri, true);

    RootDescription rootDesc = selectRootDescription(resource);
    if (rootDesc == null) return;

    createJUnitFileDescriptor(rootDesc);
    
//    EList<TestDescription> testDescriptions = rootDesc.getTestDescriptions();    
//    for (TestDescription testDesc : testDescriptions) {
//      System.out.println(generateTestMethodCode(rootDesc, testDesc));
//      System.out.println("=======================================");
//      System.out.println("=======================================");
//    }
  }
  
  private JUnitFileDesc createJUnitFileDescriptor(RootDescription rootDesc){
    JUnitFileDesc fileDesc = new JUnitFileDesc();
    fileDesc.setClassName(rootDesc.getClassContext()+"Test");
    
    EList<TestDescription> testDescriptions = rootDesc.getTestDescriptions();
    for (TestDescription testDesc : testDescriptions) {
      String methodName = testDesc.getOperation().getName();
      System.out.print("Создаем тест метода "+methodName+" --->  ");
      methodName = "test"+methodName;
      System.out.println(methodName);
      String methodBody = new String();
      
      MethodDescription testMethod = new MethodDescription(methodName, methodBody);
      fileDesc.addMethodDescription(testMethod);
      System.out.println("\tГОТОВО === тест "+methodName+" создан");      
    }
    
    return fileDesc;
  }

  private String generateTestMethodCode(RootDescription rootDesc,
      TestDescription testDesc) {
    StringBuilder result = new StringBuilder();
    String methodName = testDesc.getOperation().getName();
    String stateCondition = testDesc.getStateCondition();
    String guardCondition = testDesc.getGuardCondition();
    String targetCondition = testDesc.getTargetCondition();

    result.append("public void test").append(testDesc.getOperation().getName())
        .append("()").append("{");
    result.append("\n");

    result.append(
        "Код инициализации объекта класса " + rootDesc.getClassContext())
        .append(" в соответствии с выражением ").append(stateCondition);
    result.append("\n");

    result.append(
        "Код инициализации параметров метода "
            + testDesc.getOperation().getName()).append(" ").append(
        "в соответствии с выражением ").append(guardCondition);
    result.append("\n");

    result.append("Код вызова метода ").append(methodName);
    result.append("\n");

    result
        .append(
            "Код проверки того, что объект находится в состоянии, удовлетворяющем условию ")
        .append(targetCondition).append("}");

    return result.toString();
  }

  private RootDescription selectRootDescription(Resource resource) {
    for (Iterator<EObject> iterator = resource.getContents().iterator(); iterator
        .hasNext();) {
      EObject obj = iterator.next();
      if (obj instanceof RootDescription) {
        return (RootDescription) obj;
      }
    }
    return null;
  }

  @Override
  public boolean isEnabled() {
    return true;
  }

  @Override
  public boolean isHandled() {
    return true;
  }

  @Override
  public void removeHandlerListener(IHandlerListener handlerListener) {}

}
